@@ -2,16 +2,19 @@ module LiquidInterpolatable |
||
2 | 2 |
extend ActiveSupport::Concern |
3 | 3 |
|
4 | 4 |
def interpolate_options(options, payload) |
5 |
- duped_options = options.dup.tap do |duped_options| |
|
6 |
- duped_options.each_pair do |key, value| |
|
7 |
- if value.class == String |
|
8 |
- duped_options[key] = Liquid::Template.parse(value).render(payload) |
|
9 |
- else |
|
10 |
- duped_options[key] = value |
|
11 |
- end |
|
5 |
+ case options.class.to_s |
|
6 |
+ when 'String' |
|
7 |
+ Liquid::Template.parse(options).render(payload) |
|
8 |
+ when 'ActiveSupport::HashWithIndifferentAccess', 'Hash' |
|
9 |
+ duped_options = options.dup |
|
10 |
+ duped_options.each do |key, value| |
|
11 |
+ duped_options[key] = interpolate_options(value, payload) |
|
12 |
+ end |
|
13 |
+ when 'Array' |
|
14 |
+ options.collect do |value| |
|
15 |
+ interpolate_options(value, payload) |
|
12 | 16 |
end |
13 | 17 |
end |
14 |
- duped_options |
|
15 | 18 |
end |
16 | 19 |
|
17 | 20 |
def interpolate_string(string, payload) |
@@ -2,6 +2,8 @@ require 'rturk' |
||
2 | 2 |
|
3 | 3 |
module Agents |
4 | 4 |
class HumanTaskAgent < Agent |
5 |
+ include LiquidInterpolatable |
|
6 |
+ |
|
5 | 7 |
default_schedule "every_10m" |
6 | 8 |
|
7 | 9 |
description <<-MD |
@@ -16,7 +18,7 @@ module Agents |
||
16 | 18 |
|
17 | 19 |
# Example |
18 | 20 |
|
19 |
- If created with an event, all HIT fields can contain interpolated values via [JSONPaths](http://goessner.net/articles/JsonPath/) placed between < and > characters. |
|
21 |
+ If created with an event, all HIT fields can contain interpolated values via [liquid templating](https://github.com/cantino/huginn/wiki/Formatting-Events-using-Liquid). |
|
20 | 22 |
For example, if the incoming event was a Twitter event, you could make a HITT to rate its sentiment like this: |
21 | 23 |
|
22 | 24 |
{ |
@@ -25,7 +27,7 @@ module Agents |
||
25 | 27 |
"hit": { |
26 | 28 |
"assignments": 1, |
27 | 29 |
"title": "Sentiment evaluation", |
28 |
- "description": "Please rate the sentiment of this message: '<$.message>'", |
|
30 |
+ "description": "Please rate the sentiment of this message: '{{message}}'", |
|
29 | 31 |
"reward": 0.05, |
30 | 32 |
"lifetime_in_seconds": "3600", |
31 | 33 |
"questions": [ |
@@ -83,7 +85,7 @@ module Agents |
||
83 | 85 |
"title": "Take a poll about some jokes", |
84 | 86 |
"instructions": "Please rank these jokes from most funny (5) to least funny (1)", |
85 | 87 |
"assignments": 3, |
86 |
- "row_template": "<$.joke>" |
|
88 |
+ "row_template": "{{joke}}" |
|
87 | 89 |
}, |
88 | 90 |
"hit": { |
89 | 91 |
"assignments": 5, |
@@ -168,7 +170,7 @@ module Agents |
||
168 | 170 |
{ |
169 | 171 |
'assignments' => 1, |
170 | 172 |
'title' => "Sentiment evaluation", |
171 |
- 'description' => "Please rate the sentiment of this message: '<$.message>'", |
|
173 |
+ 'description' => "Please rate the sentiment of this message: '{{message}}'", |
|
172 | 174 |
'reward' => 0.05, |
173 | 175 |
'lifetime_in_seconds' => 24 * 60 * 60, |
174 | 176 |
'questions' => |
@@ -332,7 +334,7 @@ module Agents |
||
332 | 334 |
'name' => "Item #{index + 1}", |
333 | 335 |
'key' => index, |
334 | 336 |
'required' => "true", |
335 |
- 'question' => Utils.interpolate_jsonpaths(options['poll_options']['row_template'], assignments[index].answers), |
|
337 |
+ 'question' => interpolate_string(options['poll_options']['row_template'], assignments[index].answers), |
|
336 | 338 |
'selections' => selections |
337 | 339 |
} |
338 | 340 |
end |
@@ -387,9 +389,9 @@ module Agents |
||
387 | 389 |
|
388 | 390 |
def create_hit(opts = {}) |
389 | 391 |
payload = opts['payload'] || {} |
390 |
- title = Utils.interpolate_jsonpaths(opts['title'], payload).strip |
|
391 |
- description = Utils.interpolate_jsonpaths(opts['description'], payload).strip |
|
392 |
- questions = Utils.recursively_interpolate_jsonpaths(opts['questions'], payload) |
|
392 |
+ title = interpolate_string(opts['title'], payload).strip |
|
393 |
+ description = interpolate_string(opts['description'], payload).strip |
|
394 |
+ questions = interpolate_options(opts['questions'], payload) |
|
393 | 395 |
hit = RTurk::Hit.create(:title => title) do |hit| |
394 | 396 |
hit.max_assignments = (opts['assignments'] || 1).to_i |
395 | 397 |
hit.description = description |
@@ -2,10 +2,12 @@ require 'pp' |
||
2 | 2 |
|
3 | 3 |
module Agents |
4 | 4 |
class PeakDetectorAgent < Agent |
5 |
+ include LiquidInterpolatable |
|
6 |
+ |
|
5 | 7 |
cannot_be_scheduled! |
6 | 8 |
|
7 | 9 |
description <<-MD |
8 |
- Use a PeakDetectorAgent to watch for peaks in an event stream. When a peak is detected, the resulting Event will have a payload message of `message`. You can include extractions in the message, for example: `I saw a bar of: <foo.bar>` |
|
10 |
+ Use a PeakDetectorAgent to watch for peaks in an event stream. When a peak is detected, the resulting Event will have a payload message of `message`. You can include extractions in the message, for example: `I saw a bar of: {{foo.bar}}`, have a look at the [Wiki](https://github.com/cantino/huginn/wiki/Formatting-Events-using-Liquid) for details. |
|
9 | 11 |
|
10 | 12 |
The `value_path` value is a [JSONPaths](http://goessner.net/articles/JsonPath/) to the value of interest. `group_by_path` is a hash path that will be used to group values, if present. |
11 | 13 |
|
@@ -67,7 +69,7 @@ module Agents |
||
67 | 69 |
if newest_value > average_value + std_multiple * standard_deviation |
68 | 70 |
memory['peaks'][group] << newest_time |
69 | 71 |
memory['peaks'][group].reject! { |p| p <= newest_time - window_duration } |
70 |
- create_event :payload => { 'message' => options['message'], 'peak' => newest_value, 'peak_time' => newest_time, 'grouped_by' => group.to_s } |
|
72 |
+ create_event :payload => { 'message' => interpolate_string(options['message'], event.payload), 'peak' => newest_value, 'peak_time' => newest_time, 'grouped_by' => group.to_s } |
|
71 | 73 |
end |
72 | 74 |
end |
73 | 75 |
end |
@@ -1,5 +1,7 @@ |
||
1 | 1 |
module Agents |
2 | 2 |
class TriggerAgent < Agent |
3 |
+ include LiquidInterpolatable |
|
4 |
+ |
|
3 | 5 |
cannot_be_scheduled! |
4 | 6 |
|
5 | 7 |
VALID_COMPARISON_TYPES = %w[regex !regex field<value field<=value field==value field!=value field>=value field>value] |
@@ -13,7 +15,7 @@ module Agents |
||
13 | 15 |
|
14 | 16 |
The `value` can be a single value or an array of values. In the case of an array, if one or more values match then the rule matches. |
15 | 17 |
|
16 |
- All rules must match for the Agent to match. The resulting Event will have a payload message of `message`. You can include extractions in the message, for example: `I saw a bar of: <foo.bar>` |
|
18 |
+ All rules must match for the Agent to match. The resulting Event will have a payload message of `message`. You can use liquid templating in the `message, have a look at the [Wiki](https://github.com/cantino/huginn/wiki/Formatting-Events-using-Liquid) for details. |
|
17 | 19 |
|
18 | 20 |
Set `keep_event` to `true` if you'd like to re-emit the incoming event, optionally merged with 'message' when provided. |
19 | 21 |
|
@@ -46,7 +48,7 @@ module Agents |
||
46 | 48 |
'value' => "foo\\d+bar", |
47 | 49 |
'path' => "topkey.subkey.subkey.goal", |
48 | 50 |
}], |
49 |
- 'message' => "Looks like your pattern matched in '<value>'!" |
|
51 |
+ 'message' => "Looks like your pattern matched in '{{value}}'!" |
|
50 | 52 |
} |
51 | 53 |
end |
52 | 54 |
|
@@ -88,9 +90,9 @@ module Agents |
||
88 | 90 |
if match |
89 | 91 |
if keep_event? |
90 | 92 |
payload = event.payload.dup |
91 |
- payload['message'] = make_message(event[:payload]) if options['message'].present? |
|
93 |
+ payload['message'] = interpolate_string(options['message'], event.payload) if options['message'].present? |
|
92 | 94 |
else |
93 |
- payload = { 'message' => make_message(event[:payload]) } |
|
95 |
+ payload = { 'message' => interpolate_string(options['message'], event.payload) } |
|
94 | 96 |
end |
95 | 97 |
|
96 | 98 |
create_event :payload => payload |
@@ -1,15 +0,0 @@ |
||
1 |
-class MigrateHipchatAndEfAgentToLiquid < ActiveRecord::Migration |
|
2 |
- def up |
|
3 |
- Agent.where(:type => 'Agents::HipchatAgent').each do |agent| |
|
4 |
- LiquidMigrator.convert_all_agent_options(agent) |
|
5 |
- end |
|
6 |
- Agent.where(:type => 'Agents::EventFormattingAgent').each do |agent| |
|
7 |
- agent.options['instructions'] = LiquidMigrator.convert_hash(agent.options['instructions'], {:merge_path_attributes => true, :leading_dollarsign_is_jsonpath => true}) |
|
8 |
- agent.save |
|
9 |
- end |
|
10 |
- end |
|
11 |
- |
|
12 |
- def down |
|
13 |
- raise ActiveRecord::IrreversibleMigration, "Cannot revert migration to Liquid templating" |
|
14 |
- end |
|
15 |
-end |
@@ -1,11 +0,0 @@ |
||
1 |
-class MigratePushbulletAgentToLiquid < ActiveRecord::Migration |
|
2 |
- def up |
|
3 |
- Agent.where(:type => 'Agents::PushbulletAgent').each do |agent| |
|
4 |
- LiquidMigrator.convert_all_agent_options(agent) |
|
5 |
- end |
|
6 |
- end |
|
7 |
- |
|
8 |
- def down |
|
9 |
- raise ActiveRecord::IrreversibleMigration, "Cannot revert migration to Liquid templating" |
|
10 |
- end |
|
11 |
-end |
@@ -1,11 +0,0 @@ |
||
1 |
-class MigrateJabberAgentToLiquid < ActiveRecord::Migration |
|
2 |
- def up |
|
3 |
- Agent.where(:type => 'Agents::JabberAgent').each do |agent| |
|
4 |
- LiquidMigrator.convert_all_agent_options(agent) |
|
5 |
- end |
|
6 |
- end |
|
7 |
- |
|
8 |
- def down |
|
9 |
- raise ActiveRecord::IrreversibleMigration, "Cannot revert migration to Liquid templating" |
|
10 |
- end |
|
11 |
-end |
@@ -1,11 +0,0 @@ |
||
1 |
-class MigrateDataOutputAgentToLiquid < ActiveRecord::Migration |
|
2 |
- def up |
|
3 |
- Agent.where(:type => 'Agents::DataOutputAgent').each do |agent| |
|
4 |
- LiquidMigrator.convert_all_agent_options(agent) |
|
5 |
- end |
|
6 |
- end |
|
7 |
- |
|
8 |
- def down |
|
9 |
- raise ActiveRecord::IrreversibleMigration, "Cannot revert migration to Liquid templating" |
|
10 |
- end |
|
11 |
-end |
@@ -1,12 +0,0 @@ |
||
1 |
-class MigrateTranslationAgentToLiquid < ActiveRecord::Migration |
|
2 |
- def up |
|
3 |
- Agent.where(:type => 'Agents::TranslationAgent').each do |agent| |
|
4 |
- agent.options['content'] = LiquidMigrator.convert_hash(agent.options['content'], {:merge_path_attributes => true, :leading_dollarsign_is_jsonpath => true}) |
|
5 |
- agent.save |
|
6 |
- end |
|
7 |
- end |
|
8 |
- |
|
9 |
- def down |
|
10 |
- raise ActiveRecord::IrreversibleMigration, "Cannot revert migration to Liquid templating" |
|
11 |
- end |
|
12 |
-end |
@@ -1,14 +0,0 @@ |
||
1 |
-class MigrateTwitterPublishAgentToLiquid < ActiveRecord::Migration |
|
2 |
- def up |
|
3 |
- Agent.where(:type => 'Agents::TwitterPublishAgent').each do |agent| |
|
4 |
- if (message = agent.options.delete('message_path')).present? |
|
5 |
- agent.options['message'] = "{{#{message}}}" |
|
6 |
- agent.save |
|
7 |
- end |
|
8 |
- end |
|
9 |
- end |
|
10 |
- |
|
11 |
- def down |
|
12 |
- raise ActiveRecord::IrreversibleMigration, "Cannot revert migration to Liquid templating" |
|
13 |
- end |
|
14 |
-end |
@@ -0,0 +1,45 @@ |
||
1 |
+class MigrateAgentsToLiquidTemplating < ActiveRecord::Migration |
|
2 |
+ def up |
|
3 |
+ Agent.where(:type => 'Agents::HipchatAgent').each do |agent| |
|
4 |
+ LiquidMigrator.convert_all_agent_options(agent) |
|
5 |
+ end |
|
6 |
+ Agent.where(:type => 'Agents::EventFormattingAgent').each do |agent| |
|
7 |
+ agent.options['instructions'] = LiquidMigrator.convert_hash(agent.options['instructions'], {:merge_path_attributes => true, :leading_dollarsign_is_jsonpath => true}) |
|
8 |
+ agent.save |
|
9 |
+ end |
|
10 |
+ Agent.where(:type => 'Agents::PushbulletAgent').each do |agent| |
|
11 |
+ LiquidMigrator.convert_all_agent_options(agent) |
|
12 |
+ end |
|
13 |
+ Agent.where(:type => 'Agents::JabberAgent').each do |agent| |
|
14 |
+ LiquidMigrator.convert_all_agent_options(agent) |
|
15 |
+ end |
|
16 |
+ Agent.where(:type => 'Agents::DataOutputAgent').each do |agent| |
|
17 |
+ LiquidMigrator.convert_all_agent_options(agent) |
|
18 |
+ end |
|
19 |
+ Agent.where(:type => 'Agents::TranslationAgent').each do |agent| |
|
20 |
+ agent.options['content'] = LiquidMigrator.convert_hash(agent.options['content'], {:merge_path_attributes => true, :leading_dollarsign_is_jsonpath => true}) |
|
21 |
+ agent.save |
|
22 |
+ end |
|
23 |
+ Agent.where(:type => 'Agents::TwitterPublishAgent').each do |agent| |
|
24 |
+ if (message = agent.options.delete('message_path')).present? |
|
25 |
+ agent.options['message'] = "{{#{message}}}" |
|
26 |
+ agent.save |
|
27 |
+ end |
|
28 |
+ end |
|
29 |
+ Agent.where(:type => 'Agents::TriggerAgent').each do |agent| |
|
30 |
+ agent.options['message'] = LiquidMigrator.convert_make_message(agent.options['message']) |
|
31 |
+ agent.save |
|
32 |
+ end |
|
33 |
+ Agent.where(:type => 'Agents::PeakDetectorAgent').each do |agent| |
|
34 |
+ agent.options['message'] = LiquidMigrator.convert_make_message(agent.options['message']) |
|
35 |
+ agent.save |
|
36 |
+ end |
|
37 |
+ Agent.where(:type => 'Agents::HumanTaskAgent').each do |agent| |
|
38 |
+ LiquidMigrator.convert_all_agent_options(agent) |
|
39 |
+ end |
|
40 |
+ end |
|
41 |
+ |
|
42 |
+ def down |
|
43 |
+ raise ActiveRecord::IrreversibleMigration, "Cannot revert migration to Liquid templating" |
|
44 |
+ end |
|
45 |
+end |
@@ -22,7 +22,13 @@ module LiquidMigrator |
||
22 | 22 |
when 'ActiveSupport::HashWithIndifferentAccess' |
23 | 23 |
hash[key] = convert_hash(hash[key], options) |
24 | 24 |
when 'Array' |
25 |
- hash[key] = hash[key].collect { |k| convert_string(k, options[:leading_dollarsign_is_jsonpath])} |
|
25 |
+ hash[key] = hash[key].collect { |k| |
|
26 |
+ if k.class == String |
|
27 |
+ convert_string(k, options[:leading_dollarsign_is_jsonpath]) |
|
28 |
+ else |
|
29 |
+ convert_hash(k, options) |
|
30 |
+ end |
|
31 |
+ } |
|
26 | 32 |
end |
27 | 33 |
end |
28 | 34 |
# remove the unneeded *_path attributes |
@@ -50,6 +56,10 @@ module LiquidMigrator |
||
50 | 56 |
end |
51 | 57 |
end |
52 | 58 |
|
59 |
+ def self.convert_make_message(string) |
|
60 |
+ string.gsub(/<([^>]+)>/, "{{\\1}}") |
|
61 |
+ end |
|
62 |
+ |
|
53 | 63 |
def self.convert_json_path(string, filter = "") |
54 | 64 |
check_path(string) |
55 | 65 |
if string.start_with? '$.' |
@@ -56,6 +56,14 @@ describe LiquidMigrator do |
||
56 | 56 |
end |
57 | 57 |
end |
58 | 58 |
|
59 |
+ describe "migrating the 'make_message' format" do |
|
60 |
+ it "should work" do |
|
61 |
+ LiquidMigrator.convert_make_message('<message>').should == '{{message}}' |
|
62 |
+ LiquidMigrator.convert_make_message('<new.message>').should == '{{new.message}}' |
|
63 |
+ LiquidMigrator.convert_make_message('Hello <world>. How is <nested.life>').should == 'Hello {{world}}. How is {{nested.life}}' |
|
64 |
+ end |
|
65 |
+ end |
|
66 |
+ |
|
59 | 67 |
describe "migrating an actual agent" do |
60 | 68 |
before do |
61 | 69 |
valid_params = { |
@@ -99,5 +107,50 @@ describe LiquidMigrator do |
||
99 | 107 |
expect { LiquidMigrator.convert_all_agent_options(@agent) }. |
100 | 108 |
to raise_error("JSONPath '$.very.complex[*]' is too complex, please check your migration.") |
101 | 109 |
end |
110 |
+ |
|
111 |
+ it "should work with the human task agent" do |
|
112 |
+ valid_params = { |
|
113 |
+ 'expected_receive_period_in_days' => 2, |
|
114 |
+ 'trigger_on' => "event", |
|
115 |
+ 'hit' => |
|
116 |
+ { |
|
117 |
+ 'assignments' => 1, |
|
118 |
+ 'title' => "Sentiment evaluation", |
|
119 |
+ 'description' => "Please rate the sentiment of this message: '<$.message>'", |
|
120 |
+ 'reward' => 0.05, |
|
121 |
+ 'lifetime_in_seconds' => 24 * 60 * 60, |
|
122 |
+ 'questions' => |
|
123 |
+ [ |
|
124 |
+ { |
|
125 |
+ 'type' => "selection", |
|
126 |
+ 'key' => "sentiment", |
|
127 |
+ 'name' => "Sentiment", |
|
128 |
+ 'required' => "true", |
|
129 |
+ 'question' => "Please select the best sentiment value:", |
|
130 |
+ 'selections' => |
|
131 |
+ [ |
|
132 |
+ { 'key' => "happy", 'text' => "Happy" }, |
|
133 |
+ { 'key' => "sad", 'text' => "Sad" }, |
|
134 |
+ { 'key' => "neutral", 'text' => "Neutral" } |
|
135 |
+ ] |
|
136 |
+ }, |
|
137 |
+ { |
|
138 |
+ 'type' => "free_text", |
|
139 |
+ 'key' => "feedback", |
|
140 |
+ 'name' => "Have any feedback for us?", |
|
141 |
+ 'required' => "false", |
|
142 |
+ 'question' => "Feedback", |
|
143 |
+ 'default' => "Type here...", |
|
144 |
+ 'min_length' => "2", |
|
145 |
+ 'max_length' => "2000" |
|
146 |
+ } |
|
147 |
+ ] |
|
148 |
+ } |
|
149 |
+ } |
|
150 |
+ @agent = Agents::HumanTaskAgent.new(:name => "somename", :options => valid_params) |
|
151 |
+ @agent.user = users(:jane) |
|
152 |
+ LiquidMigrator.convert_all_agent_options(@agent) |
|
153 |
+ @agent.reload.options['hit']['description'].should == "Please rate the sentiment of this message: '{{message}}'" |
|
154 |
+ end |
|
102 | 155 |
end |
103 | 156 |
end |
@@ -1,6 +1,9 @@ |
||
1 | 1 |
require 'spec_helper' |
2 |
+require 'models/concerns/liquid_interpolatable' |
|
2 | 3 |
|
3 | 4 |
describe Agents::HumanTaskAgent do |
5 |
+ it_behaves_like LiquidInterpolatable |
|
6 |
+ |
|
4 | 7 |
before do |
5 | 8 |
@checker = Agents::HumanTaskAgent.new(:name => "my human task agent") |
6 | 9 |
@checker.options = @checker.default_options |
@@ -116,19 +119,19 @@ describe Agents::HumanTaskAgent do |
||
116 | 119 |
@checker.options['poll_options'] = { 'title' => "Take a poll about jokes", |
117 | 120 |
'instructions' => "Rank these by how funny they are", |
118 | 121 |
'assignments' => 3, |
119 |
- 'row_template' => "<$.joke>" } |
|
122 |
+ 'row_template' => "{{joke}}" } |
|
120 | 123 |
@checker.should be_valid |
121 | 124 |
@checker.options['poll_options'] = { 'instructions' => "Rank these by how funny they are", |
122 | 125 |
'assignments' => 3, |
123 |
- 'row_template' => "<$.joke>" } |
|
126 |
+ 'row_template' => "{{joke}}" } |
|
124 | 127 |
@checker.should_not be_valid |
125 | 128 |
@checker.options['poll_options'] = { 'title' => "Take a poll about jokes", |
126 | 129 |
'assignments' => 3, |
127 |
- 'row_template' => "<$.joke>" } |
|
130 |
+ 'row_template' => "{{joke}}" } |
|
128 | 131 |
@checker.should_not be_valid |
129 | 132 |
@checker.options['poll_options'] = { 'title' => "Take a poll about jokes", |
130 | 133 |
'instructions' => "Rank these by how funny they are", |
131 |
- 'row_template' => "<$.joke>" } |
|
134 |
+ 'row_template' => "{{joke}}" } |
|
132 | 135 |
@checker.should_not be_valid |
133 | 136 |
@checker.options['poll_options'] = { 'title' => "Take a poll about jokes", |
134 | 137 |
'instructions' => "Rank these by how funny they are", |
@@ -207,9 +210,9 @@ describe Agents::HumanTaskAgent do |
||
207 | 210 |
|
208 | 211 |
describe "creating hits" do |
209 | 212 |
it "can create HITs based on events, interpolating their values" do |
210 |
- @checker.options['hit']['title'] = "Hi <.name>" |
|
211 |
- @checker.options['hit']['description'] = "Make something for <.name>" |
|
212 |
- @checker.options['hit']['questions'][0]['name'] = "<.name> Question 1" |
|
213 |
+ @checker.options['hit']['title'] = "Hi {{name}}" |
|
214 |
+ @checker.options['hit']['description'] = "Make something for {{name}}" |
|
215 |
+ @checker.options['hit']['questions'][0]['name'] = "{{name}} Question 1" |
|
213 | 216 |
|
214 | 217 |
question_form = nil |
215 | 218 |
hitInterface = OpenStruct.new |
@@ -232,7 +235,7 @@ describe Agents::HumanTaskAgent do |
||
232 | 235 |
end |
233 | 236 |
|
234 | 237 |
it "works without an event too" do |
235 |
- @checker.options['hit']['title'] = "Hi <.name>" |
|
238 |
+ @checker.options['hit']['title'] = "Hi {{name}}" |
|
236 | 239 |
hitInterface = OpenStruct.new |
237 | 240 |
hitInterface.id = 123 |
238 | 241 |
mock(hitInterface).question_form(instance_of Agents::HumanTaskAgent::AgentQuestionForm) |
@@ -483,7 +486,7 @@ describe Agents::HumanTaskAgent do |
||
483 | 486 |
'title' => "Hi!", |
484 | 487 |
'instructions' => "hello!", |
485 | 488 |
'assignments' => 2, |
486 |
- 'row_template' => "This is <.sentiment>" |
|
489 |
+ 'row_template' => "This is {{sentiment}}" |
|
487 | 490 |
} |
488 | 491 |
@event.save! |
489 | 492 |
mock(RTurk::GetReviewableHITs).create { mock!.hit_ids { %w[JH3132836336DHG JH39AA63836DHG JH39AA63836DH12345] } } |
@@ -1,6 +1,9 @@ |
||
1 | 1 |
require 'spec_helper' |
2 |
+require 'models/concerns/liquid_interpolatable' |
|
2 | 3 |
|
3 | 4 |
describe Agents::PeakDetectorAgent do |
5 |
+ it_behaves_like LiquidInterpolatable |
|
6 |
+ |
|
4 | 7 |
before do |
5 | 8 |
@valid_params = { |
6 | 9 |
'name' => "my peak detector agent", |
@@ -1,6 +1,9 @@ |
||
1 | 1 |
require 'spec_helper' |
2 |
+require 'models/concerns/liquid_interpolatable' |
|
2 | 3 |
|
3 | 4 |
describe Agents::TriggerAgent do |
5 |
+ it_behaves_like LiquidInterpolatable |
|
6 |
+ |
|
4 | 7 |
before do |
5 | 8 |
@valid_params = { |
6 | 9 |
'name' => "my trigger agent", |
@@ -11,7 +14,7 @@ describe Agents::TriggerAgent do |
||
11 | 14 |
'value' => "a\\db", |
12 | 15 |
'path' => "foo.bar.baz", |
13 | 16 |
}], |
14 |
- 'message' => "I saw '<foo.bar.baz>' from <name>" |
|
17 |
+ 'message' => "I saw '{{foo.bar.baz}}' from {{name}}" |
|
15 | 18 |
} |
16 | 19 |
} |
17 | 20 |
|
@@ -20,7 +20,7 @@ shared_examples_for LiquidInterpolatable do |
||
20 | 20 |
|
21 | 21 |
describe "interpolating liquid templates" do |
22 | 22 |
it "should work" do |
23 |
- @checker.send(:interpolate_options, @checker.options, @event.payload).should == { |
|
23 |
+ @checker.interpolate_options(@checker.options, @event.payload).should == { |
|
24 | 24 |
"normal" => "just some normal text", |
25 | 25 |
"variable" => "hello", |
26 | 26 |
"text" => "Some test with an embedded hello", |
@@ -28,6 +28,26 @@ shared_examples_for LiquidInterpolatable do |
||
28 | 28 |
} |
29 | 29 |
end |
30 | 30 |
|
31 |
+ it "hsould work with arrays", focus: true do |
|
32 |
+ @checker.options = {"value" => ["{{variable}}", "Much array", "Hey, {{hello_world}}"]} |
|
33 |
+ @checker.interpolate_options(@checker.options, @event.payload).should == { |
|
34 |
+ "value" => ["hello", "Much array", "Hey, Hello world"] |
|
35 |
+ } |
|
36 |
+ end |
|
37 |
+ |
|
38 |
+ it "should work recursively" do |
|
39 |
+ @checker.options['hash'] = {'recursive' => "{{variable}}"} |
|
40 |
+ @checker.options['indifferent_hash'] = ActiveSupport::HashWithIndifferentAccess.new({'recursive' => "{{variable}}"}) |
|
41 |
+ @checker.interpolate_options(@checker.options, @event.payload).should == { |
|
42 |
+ "normal" => "just some normal text", |
|
43 |
+ "variable" => "hello", |
|
44 |
+ "text" => "Some test with an embedded hello", |
|
45 |
+ "escape" => "This should be Hello+world", |
|
46 |
+ "hash" => {'recursive' => 'hello'}, |
|
47 |
+ "indifferent_hash" => {'recursive' => 'hello'}, |
|
48 |
+ } |
|
49 |
+ end |
|
50 |
+ |
|
31 | 51 |
it "should work for strings" do |
32 | 52 |
@checker.send(:interpolate_string, "{{variable}}", @event.payload).should == "hello" |
33 | 53 |
@checker.send(:interpolate_string, "{{variable}} you", @event.payload).should == "hello you" |